﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SharedGenomics.Workbench.Core;
using SharedGenomics.Workbench.Views;
using SharedGenomics.Workbench.Models;
using SharedGenomics.Workbench.PresentationModel;
using SharedGenomics.Core;
using SharedGenomics.Domain;
using SharedGenomics.Domain.Data;
using SharedGenomics.DataAccess;
using SharedGenomics.Workbench.Services;

namespace SharedGenomics.Workbench.Presenters
{
    public class OpenGenotypeFilePresenter : TaskStagePresenter<DataFileUploadTaskContext>, IOpenGenotypeFilePresenter
    {
        public OpenGenotypeFilePresenter(IOpenGenotypeFileView view, IFileBrowserPresenter fileLoadPresenter, IEditUserMarkerPresenter editMarkerPresenter, WatchListPresenter watchListPresenter, ISnpService snpService, MissingMarkersModel model, GenotypeDataFileParserFactory genotypeFileParserFactory)
            : base(view)
        {
            //register for view events
            view.SelectedMissingMarkerChanged += new EventHandler(this.View_SelectedMissingMarkerChanged);
            view.LookupMissingMarkersClicked += new EventHandler(this.View_LookupMissingMarkersClicked);
            view.NextClicked += new EventHandler(this.View_NextClicked);

            this.GenotypeFileView = view;
            this.FileLoad = fileLoadPresenter;
            this.MarkerEdit = editMarkerPresenter;
            this.WatchListPresenter = watchListPresenter;
            this.SnpService = snpService;
            this.Model = model;
            this.GenotypeFileParserFactory = genotypeFileParserFactory;

            view.Model = model;
            view.IsMovedNextEnabled = false;
            view.IsLookupMissingMarkersEnabled = false;
            view.FileFormats = new[] { new ValueDisplayItem<GenotypeDataFileFormat>(GenotypeDataFileFormat.BCSnpMaxExport, "BCSnpMax"), new ValueDisplayItem<GenotypeDataFileFormat>(GenotypeDataFileFormat.BeadStudioExport, "Bead Studio Export") };

            //TODO: set filters on open file dialog
            //set open file prompt text
            this.FileLoad.PromptText = "Genotype file to open:";

            //register for events on dependencies
            this.FileLoad.FileOpened += new EventHandler(this.GenotypeFileLoad_FileOpened);

            EventHandler modelWatchListSyncHandler = new EventHandler((o, e) => { this.WatchListPresenter.SyncWith<string>(this.Model.Items, s => s); });
            this.Model.ListChanged += modelWatchListSyncHandler;
            this.WatchListPresenter.WatchListLoaded += modelWatchListSyncHandler;

            this.MarkerEdit.MarkerUpdated += new EventHandler<MarkerUpdatedEventArgs>(this.MarkerEdit_MarkerUpdated);
        }

        private void View_NextClicked(object sender, EventArgs e)
        {
            this.Task.TaskContext.GenotypeFilePath = this.GenotypeFilePath;
            this.Task.TaskContext.GenotypeFileFormat = this.GenotypeFileFormat;

            this.Task.MoveNext();
        }

        private void View_LookupMissingMarkersClicked(object sender, EventArgs e)
        {
            this.GenotypeFileView.IsLookupMissingMarkersEnabled = false;

            this.BackgroundExecutor.Execute(() => this.SnpService.FilterUnavailableMarkers(this.LoadedFileParser.MarkerNames),
            (or) =>
            {
                this.GenotypeFileView.IsLookupMissingMarkersEnabled = true;
                if (or.Error == null)
                {
                    or.Result.BindAction(markers =>
                    {
                        this.Model.LoadMarkers(markers);
                    });
                    //this.Model.LoadMarkers(or.Result);
                    //var missingMarkers = or.Result;

                    ////display missing markers in view and sync with watch list
                    //this.GenotypeFileView.MissingMarkers = missingMarkers;
                    //this.WatchListPresenter.SyncWith<string>(missingMarkers, s => s);
                }
                else
                {
                    this.View.DisplayError(String.Format("Unable to get missing markers: {0}", or.Error.Message));
                }
            });
        }

        private void View_SelectedMissingMarkerChanged(object sender, EventArgs e)
        {
            string selectedMarker = this.GenotypeFileView.SelectedMissingMarker;
            this.MarkerEdit.LoadMarker(selectedMarker);
        }

        private void GenotypeFileLoad_FileOpened(object sender, EventArgs e)
        {
            string genotypeFilePath = this.FileLoad.FilePath;
            this.FileLoad.IsOpenEnabled = false;
            GenotypeDataFileFormat format = this.GenotypeFileView.SelectedFileFormat;

            //parse genotype file in the background
            this.BackgroundExecutor.Execute(() =>
            {
                return this.GenotypeFileParserFactory.GetParserForFile(genotypeFilePath, format);
            },
            (or) =>
            {
                this.FileLoad.IsOpenEnabled = true;
                if (or.Error == null)
                {
                    var parser = or.Result;
                    this.GenotypeFileView.MarkerCount = parser.MarkerNames.Count;
                    this.GenotypeFileView.IndividualCount = parser.IndividualNames.Count;

                    this.LoadedFileParser = parser;
                    this.GenotypeFileView.IsLookupMissingMarkersEnabled = true;

                    //notify listeners a genotype file has been loaded
                    this.GenotypeFilePath = genotypeFilePath;
                    this.GenotypeFileFormat = format;
                    this.GenotypeFileView.IsMovedNextEnabled = true;

                    //this.GenotypeFileLoaded.Raise(this);
                }
                else
                {
                    this.View.DisplayError(String.Format("Unable to parse genotype file: {0}", or.Error.Message));
                }
            });
        }

        private void MarkerEdit_MarkerUpdated(object sender, MarkerUpdatedEventArgs e)
        {
            //remove marker from the list of missing markers since its details have been added successfully
            this.Model.RemoveMarker(e.MarkerName);
        }

        private IOpenGenotypeFileView GenotypeFileView { get; set; }

        [Region("FileBrowse")]
        public IFileBrowserPresenter FileLoad { get; private set; }

        [Region("MarkerEdit")]
        public IEditUserMarkerPresenter MarkerEdit { get; private set; }

        public GenotypeDataFileFormat GenotypeFileFormat { get; private set; }

        [Region("WatchList")]
        public WatchListPresenter WatchListPresenter { get; private set; }
        private ISnpService SnpService { get; set; }
        private MissingMarkersModel Model { get; set; }
        private IGenotypeDataFileParser LoadedFileParser { get; set; }
        private GenotypeDataFileParserFactory GenotypeFileParserFactory { get; set; }

        public event EventHandler GenotypeFileLoaded;
        public string GenotypeFilePath { get; private set; }
    }
}
